package cn.magictodo.weblog.common.runner;

import cn.magictodo.weblog.common.domain.dos.ArticleDO;
import cn.magictodo.weblog.common.domain.mapper.ArticleMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.util.*;

import static cn.magictodo.weblog.common.enums.RedisPrefixEnum.REDIS_IS_PUBLISH;

/**
 * @author liu
 * @since 2023-12-21 21:21
 * 初始化 Redis上相关数据
 */
@Component
@Slf4j
@Order(1)
public class InitRedisRunner implements CommandLineRunner {


    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
//    @Async("threadPoolTaskExecutor")
    public void run(String... args) throws Exception {
        LambdaQueryWrapper<ArticleDO> articleDOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        log.info("初始化 Redis上相关数据");
        deleteKeysByPrefix(REDIS_IS_PUBLISH.getPrefix()+"*");

        articleDOLambdaQueryWrapper.select(ArticleDO::getId, ArticleDO::getIsPublish)
                .eq(ArticleDO::getIsPublish, true);
//        开始查询文章信息
        articleMapper.selectList(articleDOLambdaQueryWrapper).forEach(articleDO -> {
            log.info("初始化 Redis上相关数据，文章ID：{}，文章是否发布：{}", articleDO.getId(), articleDO.getIsPublish());
//
            redisTemplate.opsForValue().set(REDIS_IS_PUBLISH.getPrefix() + articleDO.getId(), articleDO.getIsPublish());
        });
        log.info("初始化 Redis上相关数据完成");
    }

    /**
     *
     * @param keyPrefix 前缀
     */
    public void deleteKeysByPrefix(String keyPrefix) {
        String script =  "local cursor = 0\n" +
                "repeat\n" +
                "    local keys = redis.call('SCAN', cursor, 'MATCH', KEYS[1])\n" +
                "    cursor = tonumber(keys[1])\n" +
                "    for _, key in ipairs(keys[2]) do\n" +
                "        redis.call('DEL', key)\n" +
                "    end\n" +
                "until cursor == 0\n" +
                "return true";

        DefaultRedisScript<Boolean> redisScript = new DefaultRedisScript<>(script, Boolean.class);

        List<String> keys = new ArrayList<>();  // 通常情况下，KEYS部分参数是用来传参，操作redis里的key
        keys.add(keyPrefix);

        try {
            redisTemplate.execute(redisScript, keys, keyPrefix);
            log.warn("执行Lua脚本，删除前缀为{}的key", keyPrefix);
        } catch (Exception e) {
            // 适当地处理异常，如记录日志
            // 这里只是简单打印异常信息，实际应用中应该更详细地处理
            e.printStackTrace();
        }


    }

}
